package com.cskaoyan.mall.payment.pay.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.cskaoyan.mall.order.dto.OrderInfoDTO;
import com.cskaoyan.mall.payment.pay.PayHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author Pudding
 * @Date 2024/7/19 19:50
 * 这个类封装了和支付宝交互的一些操作方法
 */
@Slf4j
@Component
public class AlipayHelper implements PayHelper {

    @Autowired
    AlipayClient alipayClient;
    @Autowired
    CsmallAlipayConfig csmallAlipayConfig;

    /**
     * 1. 支付下单，获取支付页面
     *    这个接口期望做的事情:
     *          给支付宝服务器发请求，获取支付页面
     *          返回支付页面给浏览器，浏览器渲染出支付页面
     */
    @Override
    public String getPaymentPage(OrderInfoDTO orderInfoDTO) {

        //1. 这个request，其实就是对请求参数的封装
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();

        //2. 设置必选请求参数
        model.setOutTradeNo(orderInfoDTO.getOutTradeNo());                //外部订单交易编号
        model.setTotalAmount(orderInfoDTO.getTotalAmount().toString());   //订单总金额
        model.setSubject(orderInfoDTO.getTradeBody());                    //订单标题
        model.setProductCode("FAST_INSTANT_TRADE_PAY");                   //产品码

        //3. 可以设置一些其他的可选参数
        //3.1 设置过期时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        model.setTimeExpire(sdf.format(orderInfoDTO.getExpireTime()));//设置订单绝对超时时间

        //4. 在支付完成之后，设置两种回调方式
        //4.1 同步回调：指用户在支付完成之后，由用户本地浏览器跳转到一个回调地址，由浏览器渲染出支付页面
        request.setReturnUrl(csmallAlipayConfig.getReturnPaymentUrl());

        //4.2 异步回调
        // 支付: 8205 ----> 公网地址
        //      80 （最好是映射到80）
        request.setNotifyUrl(csmallAlipayConfig.getNotifyPaymentUrl());

        //5. 给请求对象设置请求体
        request.setBizModel(model);

        //6. 构建参数，生成签名，给支付宝服务器发请求，获取支付页面
        AlipayTradePagePayResponse response = null;
        //body就是支付页面的html代码
        try {
            response = alipayClient.pageExecute(request, "POST");
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        //返回了支付页面
        return response.getBody();
    }

    /**
     * 2. 根据订单号查询订单支付状态
     * @param outTradeNo
     * @return
     */
    @Override
    public Map<String, String> queryTradeStatus(String outTradeNo) {

        //1. 构建查询请求对象
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

        //2. 构建查询请求体对象
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();

        //3. 给请求体model设置参数
        model.setOutTradeNo(outTradeNo);

        //4. 把请求体对象放入请求对象中
        request.setBizModel(model);

        //5. 发送查询请求，获取查询响应结果
        AlipayTradeQueryResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        HashMap<String, String> map = new HashMap<>();
        map.put("code", response.getCode());
        map.put("msg", response.getMsg());
        map.put("subCode", response.getSubCode());
        map.put("subMsg", response.getSubMsg());
        map.put("tradeStatus", response.getTradeStatus());

        return map;
    }

    /**
     * 3. 根据订单编号关闭支付宝订单交易接口
     * @param outTradeNo
     */
    @Override
    public void closeTrade(String outTradeNo) {

        //1. 创建关闭交易的请求对象
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();

        //2. 创建关闭交易的请求体对象
        AlipayTradeCloseModel model = new AlipayTradeCloseModel();

        //3. 设置请求体对象model的参数
        model.setOutTradeNo(outTradeNo);

        //4. 把请求体对象model放入请求对象中
        request.setBizModel(model);

        //5. 发送关闭交易的请求，获取关闭交易的响应结果
        AlipayTradeCloseResponse response = null;
        try {
            response = alipayClient.execute(request);

            log.info("关闭交易" + response.getBody());
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
}
